home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the 3D Game Programming Gurus / gurus.iso / DirectX / dx9sdkcp.exe / SDK (C++) / Bin / DXUtils / Visual Studio 6.0 Wizards / Source Code / Template / d3dfile.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2002-11-12  |  24.3 KB  |  835 lines

  1. //-----------------------------------------------------------------------------
  2. // File: D3DFile.cpp
  3. //
  4. // Desc: Support code for loading DirectX .X files.
  5. //-----------------------------------------------------------------------------
  6. #define STRICT
  7. $$IF(DLG)
  8. #include "stdafx.h"
  9. $$ENDIF
  10. #include <tchar.h>
  11. #include <stdio.h>
  12. #include <d3d9.h>
  13. #include <d3dx9.h>
  14. #include <dxfile.h>
  15. #include <rmxfguid.h>
  16. #include <rmxftmpl.h>
  17. #include "D3DFile.h"
  18. #include "DXUtil.h"
  19.  
  20.  
  21.  
  22.  
  23. //-----------------------------------------------------------------------------
  24. // Name:
  25. // Desc:
  26. //-----------------------------------------------------------------------------
  27. CD3DMesh::CD3DMesh( TCHAR* strName )
  28. {
  29.     _tcsncpy( m_strName, strName, sizeof(m_strName) / sizeof(TCHAR) );
  30.     m_strName[sizeof(m_strName) / sizeof(TCHAR) - 1] = _T('\0');
  31.     m_pSysMemMesh        = NULL;
  32.     m_pLocalMesh         = NULL;
  33.     m_dwNumMaterials     = 0L;
  34.     m_pMaterials         = NULL;
  35.     m_pTextures          = NULL;
  36.     m_bUseMaterials      = TRUE;
  37. }
  38.  
  39.  
  40.  
  41.  
  42. //-----------------------------------------------------------------------------
  43. // Name:
  44. // Desc:
  45. //-----------------------------------------------------------------------------
  46. CD3DMesh::~CD3DMesh()
  47. {
  48.     Destroy();
  49. }
  50.  
  51.  
  52.  
  53.  
  54. //-----------------------------------------------------------------------------
  55. // Name:
  56. // Desc:
  57. //-----------------------------------------------------------------------------
  58. HRESULT CD3DMesh::Create( LPDIRECT3DDEVICE9 pd3dDevice, TCHAR* strFilename )
  59. {
  60.     TCHAR        strPath[MAX_PATH];
  61.     LPD3DXBUFFER pAdjacencyBuffer = NULL;
  62.     LPD3DXBUFFER pMtrlBuffer = NULL;
  63.     HRESULT      hr;
  64.  
  65.     // Find the path for the file, and convert it to ANSI (for the D3DX API)
  66.     DXUtil_FindMediaFileCb( strPath, sizeof(strPath), strFilename );
  67.  
  68.     // Load the mesh
  69.     if( FAILED( hr = D3DXLoadMeshFromX( strPath, D3DXMESH_SYSTEMMEM, pd3dDevice, 
  70.                                         &pAdjacencyBuffer, &pMtrlBuffer, NULL,
  71.                                         &m_dwNumMaterials, &m_pSysMemMesh ) ) )
  72.     {
  73.         return hr;
  74.     }
  75.  
  76.     // Optimize the mesh for performance
  77.     if( FAILED( hr = m_pSysMemMesh->OptimizeInplace(
  78.                         D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE,
  79.                         (DWORD*)pAdjacencyBuffer->GetBufferPointer(), NULL, NULL, NULL ) ) )
  80.     {
  81.         SAFE_RELEASE( pAdjacencyBuffer );
  82.         SAFE_RELEASE( pMtrlBuffer );
  83.         return hr;
  84.     }
  85.  
  86.     // Get material info for the mesh
  87.     // Get the array of materials out of the buffer
  88.     if( pMtrlBuffer && m_dwNumMaterials > 0 )
  89.     {
  90.         // Allocate memory for the materials and textures
  91.         D3DXMATERIAL* d3dxMtrls = (D3DXMATERIAL*)pMtrlBuffer->GetBufferPointer();
  92.         m_pMaterials = new D3DMATERIAL9[m_dwNumMaterials];
  93.         if( m_pMaterials == NULL )
  94.         {
  95.             hr = E_OUTOFMEMORY;
  96.             goto LEnd;
  97.         }
  98.         m_pTextures  = new LPDIRECT3DTEXTURE9[m_dwNumMaterials];
  99.         if( m_pTextures == NULL )
  100.         {
  101.             hr = E_OUTOFMEMORY;
  102.             goto LEnd;
  103.         }
  104.  
  105.         // Copy each material and create its texture
  106.         for( DWORD i=0; i<m_dwNumMaterials; i++ )
  107.         {
  108.             // Copy the material
  109.             m_pMaterials[i]         = d3dxMtrls[i].MatD3D;
  110.             m_pTextures[i]          = NULL;
  111.  
  112.             // Create a texture
  113.             if( d3dxMtrls[i].pTextureFilename )
  114.             {
  115.                 TCHAR strTexture[MAX_PATH];
  116.                 TCHAR strTextureTemp[MAX_PATH];
  117.                 DXUtil_ConvertAnsiStringToGenericCb( strTextureTemp, d3dxMtrls[i].pTextureFilename, sizeof(strTextureTemp) );
  118.                 DXUtil_FindMediaFileCb( strTexture, sizeof(strTexture), strTextureTemp );
  119.  
  120.                 if( FAILED( D3DXCreateTextureFromFile( pd3dDevice, strTexture, 
  121.                                                        &m_pTextures[i] ) ) )
  122.                     m_pTextures[i] = NULL;
  123.             }
  124.         }
  125.     }
  126.     hr = S_OK;
  127.  
  128. LEnd:
  129.     SAFE_RELEASE( pAdjacencyBuffer );
  130.     SAFE_RELEASE( pMtrlBuffer );
  131.  
  132.     return hr;
  133. }
  134.  
  135.  
  136.  
  137.  
  138. //-----------------------------------------------------------------------------
  139. // Name:
  140. // Desc:
  141. //-----------------------------------------------------------------------------
  142. HRESULT CD3DMesh::Create( LPDIRECT3DDEVICE9 pd3dDevice,
  143.                           LPDIRECTXFILEDATA pFileData )
  144. {
  145.     LPD3DXBUFFER pMtrlBuffer = NULL;
  146.     LPD3DXBUFFER pAdjacencyBuffer = NULL;
  147.     HRESULT      hr;
  148.  
  149.     // Load the mesh from the DXFILEDATA object
  150.     if( FAILED( hr = D3DXLoadMeshFromXof( pFileData, D3DXMESH_SYSTEMMEM, pd3dDevice,
  151.                                           &pAdjacencyBuffer, &pMtrlBuffer, NULL,
  152.                                           &m_dwNumMaterials, &m_pSysMemMesh ) ) )
  153.     {
  154.         return hr;
  155.     }
  156.  
  157.     // Optimize the mesh for performance
  158.     if( FAILED( hr = m_pSysMemMesh->OptimizeInplace(
  159.                         D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE,
  160.                         (DWORD*)pAdjacencyBuffer->GetBufferPointer(), NULL, NULL, NULL ) ) )
  161.     {
  162.         SAFE_RELEASE( pAdjacencyBuffer );
  163.         SAFE_RELEASE( pMtrlBuffer );
  164.         return hr;
  165.     }
  166.  
  167.     // Get material info for the mesh
  168.     // Get the array of materials out of the buffer
  169.     if( pMtrlBuffer && m_dwNumMaterials > 0 )
  170.     {
  171.         // Allocate memory for the materials and textures
  172.         D3DXMATERIAL* d3dxMtrls = (D3DXMATERIAL*)pMtrlBuffer->GetBufferPointer();
  173.         m_pMaterials = new D3DMATERIAL9[m_dwNumMaterials];
  174.         if( m_pMaterials == NULL )
  175.         {
  176.             hr = E_OUTOFMEMORY;
  177.             goto LEnd;
  178.         }
  179.         m_pTextures  = new LPDIRECT3DTEXTURE9[m_dwNumMaterials];
  180.         if( m_pTextures == NULL )
  181.         {
  182.             hr = E_OUTOFMEMORY;
  183.             goto LEnd;
  184.         }
  185.  
  186.         // Copy each material and create its texture
  187.         for( DWORD i=0; i<m_dwNumMaterials; i++ )
  188.         {
  189.             // Copy the material
  190.             m_pMaterials[i]         = d3dxMtrls[i].MatD3D;
  191.             m_pTextures[i]          = NULL;
  192.  
  193.             // Create a texture
  194.             if( d3dxMtrls[i].pTextureFilename )
  195.             {
  196.                 TCHAR strTexture[MAX_PATH];
  197.                 TCHAR strTextureTemp[MAX_PATH];
  198.                 DXUtil_ConvertAnsiStringToGenericCb( strTextureTemp, d3dxMtrls[i].pTextureFilename, sizeof(strTextureTemp) );
  199.                 DXUtil_FindMediaFileCb( strTexture, sizeof(strTexture), strTextureTemp );
  200.  
  201.                 if( FAILED( D3DXCreateTextureFromFile( pd3dDevice, strTexture, 
  202.                                                        &m_pTextures[i] ) ) )
  203.                     m_pTextures[i] = NULL;
  204.             }
  205.         }
  206.     }
  207.     hr = S_OK;
  208.  
  209. LEnd:
  210.     SAFE_RELEASE( pAdjacencyBuffer );
  211.     SAFE_RELEASE( pMtrlBuffer );
  212.  
  213.     return hr;
  214. }
  215.  
  216.  
  217.  
  218.  
  219. //-----------------------------------------------------------------------------
  220. // Name:
  221. // Desc:
  222. //-----------------------------------------------------------------------------
  223. HRESULT CD3DMesh::SetFVF( LPDIRECT3DDEVICE9 pd3dDevice, DWORD dwFVF )
  224. {
  225.     LPD3DXMESH pTempSysMemMesh = NULL;
  226.     LPD3DXMESH pTempLocalMesh  = NULL;
  227.  
  228.     if( m_pSysMemMesh )
  229.     {
  230.         if( FAILED( m_pSysMemMesh->CloneMeshFVF( D3DXMESH_SYSTEMMEM, dwFVF,
  231.                                                  pd3dDevice, &pTempSysMemMesh ) ) )
  232.             return E_FAIL;
  233.     }
  234.     if( m_pLocalMesh )
  235.     {
  236.         if( FAILED( m_pLocalMesh->CloneMeshFVF( 0L, dwFVF, pd3dDevice,
  237.                                                 &pTempLocalMesh ) ) )
  238.         {
  239.             SAFE_RELEASE( pTempSysMemMesh );
  240.             return E_FAIL;
  241.         }
  242.     }
  243.  
  244.     SAFE_RELEASE( m_pSysMemMesh );
  245.     SAFE_RELEASE( m_pLocalMesh );
  246.  
  247.     if( pTempSysMemMesh ) m_pSysMemMesh = pTempSysMemMesh;
  248.     if( pTempLocalMesh )  m_pLocalMesh  = pTempLocalMesh;
  249.  
  250.     // Compute normals in case the meshes have them
  251.     if( m_pSysMemMesh )
  252.         D3DXComputeNormals( m_pSysMemMesh, NULL );
  253.     if( m_pLocalMesh )
  254.         D3DXComputeNormals( m_pLocalMesh, NULL );
  255.  
  256.     return S_OK;
  257. }
  258.  
  259.  
  260.  
  261.  
  262. //-----------------------------------------------------------------------------
  263. // Name:
  264. // Desc:
  265. //-----------------------------------------------------------------------------
  266. HRESULT CD3DMesh::RestoreDeviceObjects( LPDIRECT3DDEVICE9 pd3dDevice )
  267. {
  268.     if( NULL == m_pSysMemMesh )
  269.         return E_FAIL;
  270.  
  271.     // Make a local memory version of the mesh. Note: because we are passing in
  272.     // no flags, the default behavior is to clone into local memory.
  273.     if( FAILED( m_pSysMemMesh->CloneMeshFVF( 0L, m_pSysMemMesh->GetFVF(),
  274.                                              pd3dDevice, &m_pLocalMesh ) ) )
  275.         return E_FAIL;
  276.  
  277.     return S_OK;
  278.  
  279. }
  280.  
  281.  
  282.  
  283.  
  284. //-----------------------------------------------------------------------------
  285. // Name:
  286. // Desc:
  287. //-----------------------------------------------------------------------------
  288. HRESULT CD3DMesh::InvalidateDeviceObjects()
  289. {
  290.     SAFE_RELEASE( m_pLocalMesh );
  291.  
  292.     return S_OK;
  293. }
  294.  
  295.  
  296.  
  297.  
  298. //-----------------------------------------------------------------------------
  299. // Name:
  300. // Desc:
  301. //-----------------------------------------------------------------------------
  302. HRESULT CD3DMesh::Destroy()
  303. {
  304.     InvalidateDeviceObjects();
  305.     for( UINT i=0; i<m_dwNumMaterials; i++ )
  306.         SAFE_RELEASE( m_pTextures[i] );
  307.     SAFE_DELETE_ARRAY( m_pTextures );
  308.     SAFE_DELETE_ARRAY( m_pMaterials );
  309.  
  310.     SAFE_RELEASE( m_pSysMemMesh );
  311.  
  312.     m_dwNumMaterials = 0L;
  313.  
  314.     return S_OK;
  315. }
  316.  
  317.  
  318.  
  319.  
  320. //-----------------------------------------------------------------------------
  321. // Name:
  322. // Desc:
  323. //-----------------------------------------------------------------------------
  324. HRESULT CD3DMesh::Render( LPDIRECT3DDEVICE9 pd3dDevice, bool bDrawOpaqueSubsets,
  325.                           bool bDrawAlphaSubsets )
  326. {
  327.     if( NULL == m_pLocalMesh )
  328.         return E_FAIL;
  329.  
  330.     // Frist, draw the subsets without alpha
  331.     if( bDrawOpaqueSubsets )
  332.     {
  333.         for( DWORD i=0; i<m_dwNumMaterials; i++ )
  334.         {
  335.             if( m_bUseMaterials )
  336.             {
  337.                 if( m_pMaterials[i].Diffuse.a < 1.0f )
  338.                     continue;
  339.                 pd3dDevice->SetMaterial( &m_pMaterials[i] );
  340.                 pd3dDevice->SetTexture( 0, m_pTextures[i] );
  341.             }
  342.             m_pLocalMesh->DrawSubset( i );
  343.         }
  344.     }
  345.  
  346.     // Then, draw the subsets with alpha
  347.     if( bDrawAlphaSubsets && m_bUseMaterials )
  348.     {
  349.         for( DWORD i=0; i<m_dwNumMaterials; i++ )
  350.         {
  351.             if( m_pMaterials[i].Diffuse.a == 1.0f )
  352.                 continue;
  353.  
  354.             // Set the material and texture
  355.             pd3dDevice->SetMaterial( &m_pMaterials[i] );
  356.             pd3dDevice->SetTexture( 0, m_pTextures[i] );
  357.             m_pLocalMesh->DrawSubset( i );
  358.         }
  359.     }
  360.  
  361.     return S_OK;
  362. }
  363.  
  364.  
  365.  
  366.  
  367. //-----------------------------------------------------------------------------
  368. // Name:
  369. // Desc:
  370. //-----------------------------------------------------------------------------
  371. CD3DFrame::CD3DFrame( TCHAR* strName )
  372. {
  373.     _tcsncpy( m_strName, strName, sizeof(m_strName) / sizeof(TCHAR) );
  374.     m_strName[sizeof(m_strName) / sizeof(TCHAR) - 1] = _T('\0');
  375.     D3DXMatrixIdentity( &m_mat );
  376.     m_pMesh  = NULL;
  377.  
  378.     m_pChild = NULL;
  379.     m_pNext  = NULL;
  380. }
  381.  
  382.  
  383.  
  384.  
  385. //-----------------------------------------------------------------------------
  386. // Name:
  387. // Desc:
  388. //-----------------------------------------------------------------------------
  389. CD3DFrame::~CD3DFrame()
  390. {
  391.     SAFE_DELETE( m_pChild );
  392.     SAFE_DELETE( m_pNext );
  393. }
  394.  
  395.  
  396.  
  397.  
  398. //-----------------------------------------------------------------------------
  399. // Name:
  400. // Desc:
  401. //-----------------------------------------------------------------------------
  402. bool CD3DFrame::EnumMeshes( bool (*EnumMeshCB)(CD3DMesh*,void*),
  403.                             void* pContext )
  404. {
  405.     if( m_pMesh )
  406.         EnumMeshCB( m_pMesh, pContext );
  407.     if( m_pChild )
  408.         m_pChild->EnumMeshes( EnumMeshCB, pContext );
  409.     if( m_pNext )
  410.         m_pNext->EnumMeshes( EnumMeshCB, pContext );
  411.  
  412.     return TRUE;
  413. }
  414.  
  415.  
  416.  
  417.  
  418. //-----------------------------------------------------------------------------
  419. // Name:
  420. // Desc:
  421. //-----------------------------------------------------------------------------
  422. CD3DMesh* CD3DFrame::FindMesh( TCHAR* strMeshName )
  423. {
  424.     CD3DMesh* pMesh;
  425.  
  426.     if( m_pMesh )
  427.         if( !lstrcmpi( m_pMesh->m_strName, strMeshName ) )
  428.             return m_pMesh;
  429.  
  430.     if( m_pChild )
  431.         if( NULL != ( pMesh = m_pChild->FindMesh( strMeshName ) ) )
  432.             return pMesh;
  433.  
  434.     if( m_pNext )
  435.         if( NULL != ( pMesh = m_pNext->FindMesh( strMeshName ) ) )
  436.             return pMesh;
  437.  
  438.     return NULL;
  439. }
  440.  
  441.  
  442.  
  443.  
  444. //-----------------------------------------------------------------------------
  445. // Name:
  446. // Desc:
  447. //-----------------------------------------------------------------------------
  448. CD3DFrame* CD3DFrame::FindFrame( TCHAR* strFrameName )
  449. {
  450.     CD3DFrame* pFrame;
  451.  
  452.     if( !lstrcmpi( m_strName, strFrameName ) )
  453.         return this;
  454.  
  455.     if( m_pChild )
  456.         if( NULL != ( pFrame = m_pChild->FindFrame( strFrameName ) ) )
  457.             return pFrame;
  458.  
  459.     if( m_pNext )
  460.         if( NULL != ( pFrame = m_pNext->FindFrame( strFrameName ) ) )
  461.             return pFrame;
  462.  
  463.     return NULL;
  464. }
  465.  
  466.  
  467.  
  468.  
  469. //-----------------------------------------------------------------------------
  470. // Name:
  471. // Desc:
  472. //-----------------------------------------------------------------------------
  473. HRESULT CD3DFrame::Destroy()
  474. {
  475.     if( m_pMesh )  m_pMesh->Destroy();
  476.     if( m_pChild ) m_pChild->Destroy();
  477.     if( m_pNext )  m_pNext->Destroy();
  478.  
  479.     SAFE_DELETE( m_pMesh );
  480.     SAFE_DELETE( m_pNext );
  481.     SAFE_DELETE( m_pChild );
  482.  
  483.     return S_OK;
  484. }
  485.  
  486.  
  487.  
  488.  
  489. //-----------------------------------------------------------------------------
  490. // Name:
  491. // Desc:
  492. //-----------------------------------------------------------------------------
  493. HRESULT CD3DFrame::RestoreDeviceObjects( LPDIRECT3DDEVICE9 pd3dDevice )
  494. {
  495.     if( m_pMesh )  m_pMesh->RestoreDeviceObjects( pd3dDevice );
  496.     if( m_pChild ) m_pChild->RestoreDeviceObjects( pd3dDevice );
  497.     if( m_pNext )  m_pNext->RestoreDeviceObjects( pd3dDevice );
  498.     return S_OK;
  499. }
  500.  
  501.  
  502.  
  503.  
  504. //-----------------------------------------------------------------------------
  505. // Name:
  506. // Desc:
  507. //-----------------------------------------------------------------------------
  508. HRESULT CD3DFrame::InvalidateDeviceObjects()
  509. {
  510.     if( m_pMesh )  m_pMesh->InvalidateDeviceObjects();
  511.     if( m_pChild ) m_pChild->InvalidateDeviceObjects();
  512.     if( m_pNext )  m_pNext->InvalidateDeviceObjects();
  513.     return S_OK;
  514. }
  515.  
  516.  
  517.  
  518.  
  519. //-----------------------------------------------------------------------------
  520. // Name:
  521. // Desc:
  522. //-----------------------------------------------------------------------------
  523. HRESULT CD3DFrame::Render( LPDIRECT3DDEVICE9 pd3dDevice, bool bDrawOpaqueSubsets,
  524.                            bool bDrawAlphaSubsets, D3DXMATRIX* pmatWorldMatrix )
  525. {
  526.     // For pure devices, specify the world transform. If the world transform is not
  527.     // specified on pure devices, this function will fail.
  528.  
  529.     D3DXMATRIXA16 matSavedWorld, matWorld;
  530.  
  531.     if ( NULL == pmatWorldMatrix )
  532.         pd3dDevice->GetTransform( D3DTS_WORLD, &matSavedWorld );
  533.     else
  534.         matSavedWorld = *pmatWorldMatrix;
  535.  
  536.     D3DXMatrixMultiply( &matWorld, &m_mat, &matSavedWorld );
  537.     pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
  538.  
  539.     if( m_pMesh )
  540.         m_pMesh->Render( pd3dDevice, bDrawOpaqueSubsets, bDrawAlphaSubsets );
  541.  
  542.     if( m_pChild )
  543.         m_pChild->Render( pd3dDevice, bDrawOpaqueSubsets, bDrawAlphaSubsets, &matWorld );
  544.  
  545.     pd3dDevice->SetTransform( D3DTS_WORLD, &matSavedWorld );
  546.  
  547.     if( m_pNext )
  548.         m_pNext->Render( pd3dDevice, bDrawOpaqueSubsets, bDrawAlphaSubsets, &matSavedWorld );
  549.  
  550.     return S_OK;
  551. }
  552.  
  553.  
  554.  
  555.  
  556. //-----------------------------------------------------------------------------
  557. // Name:
  558. // Desc:
  559. //-----------------------------------------------------------------------------
  560. HRESULT CD3DFile::LoadFrame( LPDIRECT3DDEVICE9 pd3dDevice,
  561.                              LPDIRECTXFILEDATA pFileData,
  562.                              CD3DFrame* pParentFrame )
  563. {
  564.     LPDIRECTXFILEDATA   pChildData = NULL;
  565.     LPDIRECTXFILEOBJECT pChildObj = NULL;
  566.     const GUID* pGUID;
  567.     DWORD       cbSize;
  568.     CD3DFrame*  pCurrentFrame;
  569.     HRESULT     hr;
  570.  
  571.     // Get the type of the object
  572.     if( FAILED( hr = pFileData->GetType( &pGUID ) ) )
  573.         return hr;
  574.  
  575.     if( *pGUID == TID_D3DRMMesh )
  576.     {
  577.         hr = LoadMesh( pd3dDevice, pFileData, pParentFrame );
  578.         if( FAILED(hr) )
  579.             return hr;
  580.     }
  581.     if( *pGUID == TID_D3DRMFrameTransformMatrix )
  582.     {
  583.         D3DXMATRIX* pmatMatrix;
  584.         hr = pFileData->GetData( NULL, &cbSize, (void**)&pmatMatrix );
  585.         if( FAILED(hr) )
  586.             return hr;
  587.  
  588.         // Update the parent's matrix with the new one
  589.         pParentFrame->SetMatrix( pmatMatrix );
  590.     }
  591.     if( *pGUID == TID_D3DRMFrame )
  592.     {
  593.         // Get the frame name
  594.         CHAR  strAnsiName[512] = "";
  595.         TCHAR strName[512];
  596.         DWORD dwNameLength = 512;
  597.         if( FAILED( hr = pFileData->GetName( strAnsiName, &dwNameLength ) ) )
  598.             return hr;
  599.         DXUtil_ConvertAnsiStringToGenericCb( strName, strAnsiName, sizeof(strName) );
  600.  
  601.         // Create the frame
  602.         pCurrentFrame = new CD3DFrame( strName );
  603.         if( pCurrentFrame == NULL )
  604.             return E_OUTOFMEMORY;
  605.  
  606.         pCurrentFrame->m_pNext = pParentFrame->m_pChild;
  607.         pParentFrame->m_pChild = pCurrentFrame;
  608.  
  609.         // Enumerate child objects
  610.         while( SUCCEEDED( pFileData->GetNextObject( &pChildObj ) ) )
  611.         {
  612.             // Query the child for its FileData
  613.             hr = pChildObj->QueryInterface( IID_IDirectXFileData,
  614.                                             (void**)&pChildData );
  615.             if( SUCCEEDED(hr) )
  616.             {
  617.                 hr = LoadFrame( pd3dDevice, pChildData, pCurrentFrame );
  618.                 pChildData->Release();
  619.             }
  620.  
  621.             pChildObj->Release();
  622.  
  623.             if( FAILED(hr) )
  624.                 return hr;
  625.         }
  626.     }
  627.  
  628.     return S_OK;
  629. }
  630.  
  631.  
  632.  
  633.  
  634. //-----------------------------------------------------------------------------
  635. // Name:
  636. // Desc:
  637. //-----------------------------------------------------------------------------
  638. HRESULT CD3DFile::LoadMesh( LPDIRECT3DDEVICE9 pd3dDevice,
  639.                             LPDIRECTXFILEDATA pFileData,
  640.                             CD3DFrame* pParentFrame )
  641. {
  642.     // Currently only allowing one mesh per frame
  643.     if( pParentFrame->m_pMesh )
  644.         return E_FAIL;
  645.  
  646.     // Get the mesh name
  647.     CHAR  strAnsiName[512] = {0};
  648.     TCHAR strName[512];
  649.     DWORD dwNameLength = 512;
  650.     HRESULT hr;
  651.     if( FAILED( hr = pFileData->GetName( strAnsiName, &dwNameLength ) ) )
  652.         return hr;
  653.     DXUtil_ConvertAnsiStringToGenericCb( strName, strAnsiName, sizeof(strName) );
  654.  
  655.     // Create the mesh
  656.     pParentFrame->m_pMesh = new CD3DMesh( strName );
  657.     if( pParentFrame->m_pMesh == NULL )
  658.         return E_OUTOFMEMORY;
  659.     pParentFrame->m_pMesh->Create( pd3dDevice, pFileData );
  660.  
  661.     return S_OK;
  662. }
  663.  
  664.  
  665.  
  666.  
  667. //-----------------------------------------------------------------------------
  668. // Name:
  669. // Desc:
  670. //-----------------------------------------------------------------------------
  671. HRESULT CD3DFile::CreateFromResource( LPDIRECT3DDEVICE9 pd3dDevice, TCHAR* strResource, TCHAR* strType )
  672. {
  673.     LPDIRECTXFILE           pDXFile   = NULL;
  674.     LPDIRECTXFILEENUMOBJECT pEnumObj  = NULL;
  675.     LPDIRECTXFILEDATA       pFileData = NULL;
  676.     HRESULT hr;
  677.  
  678.     // Create a x file object
  679.     if( FAILED( hr = DirectXFileCreate( &pDXFile ) ) )
  680.         return E_FAIL;
  681.  
  682.     // Register templates for d3drm and patch extensions.
  683.     if( FAILED( hr = pDXFile->RegisterTemplates( (void*)D3DRM_XTEMPLATES,
  684.                                                  D3DRM_XTEMPLATE_BYTES ) ) )
  685.     {
  686.         pDXFile->Release();
  687.         return E_FAIL;
  688.     }
  689.     
  690.     CHAR strTypeAnsi[MAX_PATH];
  691.     DXUtil_ConvertGenericStringToAnsiCb( strTypeAnsi, strType, sizeof(strTypeAnsi) );
  692.  
  693.     DXFILELOADRESOURCE dxlr;
  694.     dxlr.hModule = NULL;
  695.     dxlr.lpName = strResource;
  696.     dxlr.lpType = (TCHAR*) strTypeAnsi;
  697.  
  698.     // Create enum object
  699.     hr = pDXFile->CreateEnumObject( (void*)&dxlr, DXFILELOAD_FROMRESOURCE, 
  700.                                     &pEnumObj );
  701.     if( FAILED(hr) )
  702.     {
  703.         pDXFile->Release();
  704.         return hr;
  705.     }
  706.  
  707.     // Enumerate top level objects (which are always frames)
  708.     while( SUCCEEDED( pEnumObj->GetNextDataObject( &pFileData ) ) )
  709.     {
  710.         hr = LoadFrame( pd3dDevice, pFileData, this );
  711.         pFileData->Release();
  712.         if( FAILED(hr) )
  713.         {
  714.             pEnumObj->Release();
  715.             pDXFile->Release();
  716.             return E_FAIL;
  717.         }
  718.     }
  719.  
  720.     SAFE_RELEASE( pFileData );
  721.     SAFE_RELEASE( pEnumObj );
  722.     SAFE_RELEASE( pDXFile );
  723.  
  724.     return S_OK;
  725. }
  726.  
  727.  
  728.  
  729.  
  730. //-----------------------------------------------------------------------------
  731. // Name:
  732. // Desc:
  733. //-----------------------------------------------------------------------------
  734. HRESULT CD3DFile::Create( LPDIRECT3DDEVICE9 pd3dDevice, TCHAR* strFilename )
  735. {
  736.     LPDIRECTXFILE           pDXFile   = NULL;
  737.     LPDIRECTXFILEENUMOBJECT pEnumObj  = NULL;
  738.     LPDIRECTXFILEDATA       pFileData = NULL;
  739.     HRESULT hr;
  740.  
  741.     // Create a x file object
  742.     if( FAILED( hr = DirectXFileCreate( &pDXFile ) ) )
  743.         return E_FAIL;
  744.  
  745.     // Register templates for d3drm and patch extensions.
  746.     if( FAILED( hr = pDXFile->RegisterTemplates( (void*)D3DRM_XTEMPLATES,
  747.                                                  D3DRM_XTEMPLATE_BYTES ) ) )
  748.     {
  749.         pDXFile->Release();
  750.         return E_FAIL;
  751.     }
  752.  
  753.     // Find the path to the file, and convert it to ANSI (for the D3DXOF API)
  754.     TCHAR strPath[MAX_PATH];
  755.     CHAR  strPathANSI[MAX_PATH];
  756.     DXUtil_FindMediaFileCb( strPath, sizeof(strPath), strFilename );
  757.     DXUtil_ConvertGenericStringToAnsiCb( strPathANSI, strPath, sizeof(strPathANSI) );
  758.     
  759.     // Create enum object
  760.     hr = pDXFile->CreateEnumObject( (void*)strPathANSI, DXFILELOAD_FROMFILE, 
  761.                                     &pEnumObj );
  762.     if( FAILED(hr) )
  763.     {
  764.         pDXFile->Release();
  765.         return hr;
  766.     }
  767.  
  768.     // Enumerate top level objects (which are always frames)
  769.     while( SUCCEEDED( pEnumObj->GetNextDataObject( &pFileData ) ) )
  770.     {
  771.         hr = LoadFrame( pd3dDevice, pFileData, this );
  772.         pFileData->Release();
  773.         if( FAILED(hr) )
  774.         {
  775.             pEnumObj->Release();
  776.             pDXFile->Release();
  777.             return E_FAIL;
  778.         }
  779.     }
  780.  
  781.     SAFE_RELEASE( pFileData );
  782.     SAFE_RELEASE( pEnumObj );
  783.     SAFE_RELEASE( pDXFile );
  784.  
  785.     return S_OK;
  786. }
  787.  
  788.  
  789.  
  790.  
  791. //-----------------------------------------------------------------------------
  792. // Name:
  793. // Desc:
  794. //-----------------------------------------------------------------------------
  795. HRESULT CD3DFile::Render( LPDIRECT3DDEVICE9 pd3dDevice, D3DXMATRIX* pmatWorldMatrix )
  796. {
  797.  
  798.     // For pure devices, specify the world transform. If the world transform is not
  799.     // specified on pure devices, this function will fail.
  800.  
  801.     // Set up the world transformation
  802.     D3DXMATRIX matSavedWorld, matWorld;
  803.  
  804.     if ( NULL == pmatWorldMatrix )
  805.         pd3dDevice->GetTransform( D3DTS_WORLD, &matSavedWorld );
  806.     else
  807.         matSavedWorld = *pmatWorldMatrix;
  808.  
  809.     D3DXMatrixMultiply( &matWorld, &matSavedWorld, &m_mat );
  810.     pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
  811.  
  812.     // Render opaque subsets in the meshes
  813.     if( m_pChild )
  814.         m_pChild->Render( pd3dDevice, TRUE, FALSE, &matWorld );
  815.  
  816.     // Enable alpha blending
  817.     pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
  818.     pd3dDevice->SetRenderState( D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA );
  819.     pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
  820.  
  821.     // Render alpha subsets in the meshes
  822.     if( m_pChild )
  823.         m_pChild->Render( pd3dDevice, FALSE, TRUE, &matWorld );
  824.  
  825.     // Restore state
  826.     pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
  827.     pd3dDevice->SetTransform( D3DTS_WORLD, &matSavedWorld );
  828.  
  829.     return S_OK;
  830. }
  831.  
  832.  
  833.  
  834.  
  835.